package vboot.core.module.mon.log.oper;

import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import lombok.RequiredArgsConstructor;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import vboot.core.common.utils.lang.IdUtils;

import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.*;

@Service
@RequiredArgsConstructor
public class MonLogOperService{
    private final MonLogOperRepo repo;
//
//    @Override
//    public Object queryAll(LogQueryCriteria criteria, Pageable pageable) {
//        Page<Log> page = logRepository.findAll(((root, criteriaQuery, cb) -> QueryHelp.getPredicate(root, criteria, cb)), pageable);
//        String status = "ERROR";
//        if (status.equals(criteria.getLogType())) {
//            return PageUtil.toPage(page.map(logErrorMapper::toDto));
//        }
//        return page;
//    }
//
//    @Override
//    public List<Log> queryAll(LogQueryCriteria criteria) {
//        return logRepository.findAll(((root, criteriaQuery, cb) -> QueryHelp.getPredicate(root, criteria, cb)));
//    }
//
//    @Override
//    public Object queryAllByUser(LogQueryCriteria criteria, Pageable pageable) {
//        Page<Log> page = logRepository.findAll(((root, criteriaQuery, cb) -> QueryHelp.getPredicate(root, criteria, cb)), pageable);
//        return PageUtil.toPage(page.map(logSmallMapper::toDto));
//    }

    @Transactional(rollbackFor = Exception.class)
    public void save(String username, String ageos,String browser, String ip, ProceedingJoinPoint joinPoint, MonLogOper log) {
        if (log == null) {
            throw new IllegalArgumentException("Log 不能为 null!");
        }
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        Oplog aopLog = method.getAnnotation(Oplog.class);

        // 方法路径
        String methodName = joinPoint.getTarget().getClass().getName() + "." + signature.getName() + "()";
        log.setId(IdUtils.getUID());
        // 描述
        log.setName(aopLog.value());
        
        log.setIp(ip);
        log.setAgeos(ageos);
//        log.setAddress(StringUtils.getCityInfo(log.getRequestIp()));
        log.setMethod(methodName);
        log.setUseid(username);
        log.setParam(getParameter(method, joinPoint.getArgs()));
        // 记录登录用户，隐藏密码信息
        if(log.getName().equals("用户登录")){
            JSONObject obj = JSONUtil.parseObj(log.getParam());
            log.setUseid(obj.get("username").toString());
            log.setParam(JSONUtil.toJsonStr(Dict.create().set("username", log.getUseid())));
        }
        log.setAgbro(browser);
        repo.save(log);
    }

    /**
     * 根据方法和传入的参数获取请求参数
     */
    private String getParameter(Method method, Object[] args) {
        List<Object> argList = new ArrayList<>();
        Parameter[] parameters = method.getParameters();
        for (int i = 0; i < parameters.length; i++) {
            //将RequestBody注解修饰的参数作为请求参数
            RequestBody requestBody = parameters[i].getAnnotation(RequestBody.class);
            if (requestBody != null) {
                argList.add(args[i]);
            }
            //将RequestParam注解修饰的参数作为请求参数
            RequestParam requestParam = parameters[i].getAnnotation(RequestParam.class);
            if (requestParam != null) {
                Map<String, Object> map = new HashMap<>(4);
                String key = parameters[i].getName();
                if (!StrUtil.isBlank(requestParam.value())) {
                    key = requestParam.value();
                }
                map.put(key, args[i]);
                argList.add(map);
            }
        }
        if (argList.isEmpty()) {
            return "";
        }
        return argList.size() == 1 ? JSONUtil.toJsonStr(argList.get(0)) : JSONUtil.toJsonStr(argList);
    }

    @Transactional(readOnly = true)
    public MonLogOper findOne(String id) {
        return repo.findById(id).get();
    }

//    @Override
//    public Object findByErrDetail(Long id) {
//        Log log = logRepository.findById(id).orElseGet(Log::new);
//        ValidationUtil.isNull(log.getId(), "Log", "id", id);
//        byte[] details = log.getExceptionDetail();
//        return Dict.create().set("exception", new String(ObjectUtil.isNotNull(details) ? details : "".getBytes()));
//    }

//    @Override
//    public void download(List<Log> logs, HttpServletResponse response) throws IOException {
//        List<Map<String, Object>> list = new ArrayList<>();
//        for (Log log : logs) {
//            Map<String, Object> map = new LinkedHashMap<>();
//            map.put("用户名", log.getUsername());
//            map.put("IP", log.getRequestIp());
//            map.put("IP来源", log.getAddress());
//            map.put("描述", log.getDescription());
//            map.put("浏览器", log.getBrowser());
//            map.put("请求耗时/毫秒", log.getTime());
//            map.put("异常详情", new String(ObjectUtil.isNotNull(log.getExceptionDetail()) ? log.getExceptionDetail() : "".getBytes()));
//            map.put("创建日期", log.getCreateTime());
//            list.add(map);
//        }
//        FileUtil.downloadExcel(list, response);
//    }

    public void delAll() {
        repo.deleteAll();
    }

    public int delete(String[] ids) {
        for (String id : ids) {
            repo.deleteById(id);
        }
        return ids.length;
    }

//
//    @Override
//    @Transactional(rollbackFor = Exception.class)
//    public void delAllByInfo() {
//        logRepository.deleteByLogType("INFO");
//    }
}
